package com.atg.atgchat.init.user.service;

import com.atg.atgchat.init.exception.BusinessException;
import com.atg.atgchat.init.exception.CommonErrorEnum;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

/*
author: atg
time: 2025/1/17 14:02
*/
@Service
@Slf4j
public class LockService {
    @Resource
    private RedissonClient redissonClient;
    @SneakyThrows
    public <T> T executeLock(String lockKey, int waitTime, TimeUnit timeUnit, Supplier<T> supplier){
        RLock lock = redissonClient.getLock(lockKey);
        boolean b = lock.tryLock(waitTime, timeUnit);
        if(!b){
           throw  new BusinessException(CommonErrorEnum.LOCK_LIMIT);
        }
        try{
            return supplier.get();
        }finally {
            lock.unlock();
        }
    }
    public <T> T executeLock(String lockKey,  Supplier<T> supplier){
        return executeLock(lockKey, -1, TimeUnit.MILLISECONDS, supplier);
    }
    // 返回不想要null
    public <T> T executeLock(String lockKey, Runnable runnable){
        return executeLock(lockKey, -1, TimeUnit.MILLISECONDS, ()->{
            runnable.run();
            return null;
        });
    }

    @FunctionalInterface
    public interface Supplier<T> {

        /**
         * Gets a result.
         *
         * @return a result
         */
        T get() throws Throwable;
    }

}

